package cn.stronglink.esm27.collection.iot.devices.esm27;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.TooManyListenersException;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;

import cn.stronglink.esm27.collection.iot.devices.esm27.response.ESM27ServerListener;
import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.UnsupportedCommOperationException;

/**
 * ESM27服务
 * @author yuzhantao
 *
 */
public class ESM27Server implements ApplicationListener<ApplicationEvent>{
//	private final static Logger logger = LogManager.getLogger(ESM27Server.class.getName());
	
	private ESM27ServerListener listener;
	// 输入输出流
	private InputStream inputStream;
	private OutputStream outputStream;

	protected CommPortIdentifier portIdentifier;
	protected CommPort commPort;
	
	/**
	 * 端口名
	 */
	private String serialPortName;
	/**
	 * 端口号
	 */
	private int serialPortBaudRate;
	
	public ESM27Server(){
	}


	public String getSerialPortName() {
		return serialPortName;
	}

	public void setSerialPortName(String serialPortName) {
		this.serialPortName = serialPortName;
	}

	public int getSerialPortBaudRate() {
		return serialPortBaudRate;
	}

	public void setSerialPortBaudRate(int serialPortBaudRate) {
		this.serialPortBaudRate = serialPortBaudRate;
	}

	/**
	 * 初始化串口
	 * @throws NoSuchPortException 
	 * @throws PortInUseException 
	 * @throws UnsupportedCommOperationException 
	 * @throws TooManyListenersException 
	 * @throws IOException 
	 */
	@SuppressWarnings("unused")
	public void openSerialPort() throws NoSuchPortException, PortInUseException, UnsupportedCommOperationException, TooManyListenersException, IOException {
		if(this.listener==null) {
			this.listener = new ESM27ServerListener();
		}
		closeSerialPort();
		portIdentifier = CommPortIdentifier.getPortIdentifier(this.getSerialPortName());
		commPort = portIdentifier.open(this.getSerialPortName(), 5000);
		
		if (commPort instanceof SerialPort) {
			SerialPort serialPort = (SerialPort) commPort;
			// 设置串口参数（波特率，数据位8，停止位1，校验位无）baudRate
			serialPort.setSerialPortParams(this.getSerialPortBaudRate(), SerialPort.DATABITS_8,
					SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
			serialPort.addEventListener(this.listener);
			serialPort.notifyOnDataAvailable(true);
			System.out.println("开启串口成功，串口名称：" + this.getSerialPortName());
			this.outputStream = serialPort.getOutputStream();
			this.inputStream = serialPort.getInputStream();
			this.listener.setInputStream(inputStream);
		}
	}

	/**
	 * 关闭串口
	 */
	public synchronized void closeSerialPort() {
		
		try {
			if(commPort!=null) {
				SerialPort sp = (SerialPort)commPort;
				sp.notifyOnDataAvailable(false);
				sp.removeEventListener();
				
				try {
					if(this.outputStream!=null) {
						this.outputStream.close();
					}
				}catch(Exception e) {
					e.printStackTrace();
				}
				try {
					if(this.inputStream!=null) {
						this.inputStream.close();
					}
				}catch(Exception e) {
					e.printStackTrace();
				}
				
				sp.close();
				sp=null;
			}
			if(portIdentifier!=null) {
				portIdentifier=null;
			}
		}catch(Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 获取串口列表
	 * @return
	 */
	public List<String> getSerialPortList() {
		List<String> serialPortList = new ArrayList<>();
		@SuppressWarnings({ "unchecked", "static-access" })
		Enumeration<CommPortIdentifier> portList = portIdentifier.getPortIdentifiers();
		while (portList.hasMoreElements()) {
			CommPortIdentifier portId = (CommPortIdentifier) portList.nextElement();
            if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
            	serialPortList.add(portId.getName());
            }
        }
		
		return serialPortList;
	}
	
	/**
	 * 发送数据
	 * 
	 * @param datas
	 * @throws IOException
	 */
	public synchronized void send(byte[] datas) throws IOException {
		outputStream.write(datas);
		outputStream.flush();
	}

	/**
	 * 是否链接
	 * @return
	 */
	public boolean isConnection() {
		return this.outputStream!=null;
	}

	@Override
	public void onApplicationEvent(ApplicationEvent event) {
//		try {
//			this.openSerialPort();
//		} catch (NoSuchPortException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		} catch (PortInUseException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		} catch (UnsupportedCommOperationException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		} catch (TooManyListenersException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		} catch (IOException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
	}
}
